#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <omp.h>
#include "util.h"

#define NUM_BYTES 1336054
#define NUM_TH 4

int main(int argc, char **argv){

	double tempo, inicial = omp_get_wtime();
	double tempoPal = 0, tempoPalIni = 0, tempoFrase = 0, tempoFraseIni = 0;
	int chamadaPalim = 0, chamadaFrase = 0; 

	int seek, numPalavras = 0, numFrases = 0, rank;
	int i, j;
	char **texto, *aux;
	char c;
	FILE *arq;

	arq = fopen("shakespe.txt", "r");
	
    	seek = NUM_BYTES;

	omp_set_num_threads(NUM_TH);

	/* Usado para guardar um pedaço de palavra que foi cortado durante a decomposição */
	aux = (char *)malloc(TAM_FRASE*sizeof(char));
	/* Armazena blocos de textos para as threads */
	texto = (char **)malloc(NUM_TH*sizeof(char *));

	/*
		Faz a leitura de blocos de texto para distribuição entre as threads
	*/
	for(i = 0; i < NUM_TH; i++){
		texto[i] = (char*)malloc((seek + TAM_FRASE + 1)*sizeof(char));

		/*
			Lê um bloco do arquivo e passa para memória
		*/
		fread(texto[i], sizeof(char), seek, arq);
			
		/*
			Verifica se o bloco de texto termina no meio de uma palavra,
			se isso ocorrer percorre o texto até achar um fim de frase,
			isto evita que palavras sejam dividas ao meio entre duas threads
		*/
		j = 0;
		c = fgetc(arq);
		if(c != -1){
			/* Anda no arquivo até achar algo que indique fim de frase */
			while(c != '\n' && c != '!' && c != '?' && c != ';' && c != ':' && c != '\r' )
			{
				aux[j] = c;
				c = fgetc(arq);
				j++;
		
			}
				aux[j] = '\0';
				/* Concatena o pedaço cortado da palavra com o bloco anterior */
				strcat(texto[i], aux);
				seek = NUM_BYTES - j;
		}
		
	}
	fclose(arq);

	/*
		Cada thread opera em cima do seu vetor correspondente, que foi criado no passo anterior
	*/
	#pragma omp parallel private (rank) reduction(+: numPalavras, numFrases, tempoPal, tempoPalIni, tempoFrase, tempoFraseIni, chamadaPalim, chamadaFrase)
	{
			rank = omp_get_thread_num();

			/*
				Chama a função separaPalavra para o bloco texto[rank], dentro dessa função as
				palavras são parseadas e verificadas quanto a palíndromos.
			*/
			tempoPalIni = omp_get_wtime();
			        numPalavras += separaPalavra(texto[rank],&chamadaPalim);
			tempoPal = tempoPal + (omp_get_wtime() - tempoPalIni);

			/*
				Chama a função separaFrase para o bloco texto[rank], dentra dessa função as
				frases são parseadas e verificadas quanto a palíndromos.
			*/
			tempoFraseIni = omp_get_wtime();
        			numFrases += separaFrase(texto[rank],&chamadaFrase);
			tempoFrase = tempoFrase + (omp_get_wtime() - tempoFraseIni);
	
			printf("Processo %d - Palindromos: [%d , %.2lf] - Frases: [%d , %.2lf]\n",omp_get_thread_num(),chamadaPalim, tempoPal,chamadaFrase, tempoFrase);
	}


	tempo = omp_get_wtime() - inicial;

	printf("\nQuantidade de palindromos de palavras: %d\n", numPalavras);
   	printf("Quantidade de palindromos de frase: %d\n", numFrases);
	printf("Tempo de execução: %.2lf seg\n", tempo);

return 0;
}
